﻿#region Copyright (c) Lokad 2010
// This code is released under the terms of the new BSD licence.
// URL: http://www.lokad.com/
#endregion
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Xml;
using System.Xml.Linq;

namespace Lokad.Monitoring.Persistence.Serialization
{
    /// <summary>Apply GZip compression over <see cref="PoxSerializer"/>.</summary>
    public class GzipPoxSerializer
    {
        static XmlObjectSerializer GetXmlSerializer(Type type)
        {
            return new PoxSerializer(type);
        }

        public void Serialize(Stream destination, object instance)
        {
            var serializer = GetXmlSerializer(instance.GetType());

            using (var compressed = destination.Compress(true))
            using (var writer = XmlDictionaryWriter.CreateBinaryWriter(compressed, null, null, false))
            {
                serializer.WriteObject(writer, instance);
            }
        }

        public object Deserialize(Stream source, Type type)
        {
            var serializer = GetXmlSerializer(type);

            using (var decompressed = source.Decompress(true))
            using (var reader = XmlDictionaryReader.CreateBinaryReader(decompressed, XmlDictionaryReaderQuotas.Max))
            {
                return serializer.ReadObject(reader);
            }
        }

        public XElement UnpackXml(Stream source)
        {
            using (var decompressed = source.Decompress(true))
            using (var reader = XmlDictionaryReader.CreateBinaryReader(decompressed, XmlDictionaryReaderQuotas.Max))
            {
                return XElement.Load(reader);
            }
        }

        public void RepackXml(Stream destination, XElement data)
        {
            using (var compressed = destination.Compress(true))
            using (var writer = XmlDictionaryWriter.CreateBinaryWriter(compressed, null, null, false))
            {
                data.Save(writer);
                writer.Flush();
                compressed.Flush();
            }
        }
    }
}
